package com.suning.sawp.service.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jxls.common.Context;
import org.jxls.util.JxlsHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import com.suning.framework.lang2.exception.BizzException;
import com.suning.rsf.ServiceException;
import com.suning.sawp.constants.ExportConstants;

public class ExcelUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtils.class);

    private static final int TWOZERO = 20;
    private static final float THREESEVENFIVE = 37.5f;
    private static final int ZERO = 0;
    private static final int TWOFIVEFIVE = 255;
    private static final int TWOFIVESIX = 256;

    public ExcelUtils() {
    }

    /**
     * 
     * 下载导出模板
     * 
     * @param fileName 文件名
     * @param titles 列标题
     * @param response
     */
    public static void downloadXlsTemplate(String fileName, String[] titles, HttpServletResponse response) {
        HSSFWorkbook creXls = new HSSFWorkbook(); // 产生工作簿对象
        HSSFSheet creSheet = creXls.createSheet(fileName); // 产生工作表对象
        try {
            if (titles != null && titles.length > 0) {
                // 产生一行
                HSSFRow tempRow = creSheet.createRow(0);

                // 获取到Excel文件中的所有的列­
                for (int j = 0; j < titles.length; j++) {
                    // 产生第一个单元格
                    HSSFCell tempCell = tempRow.createCell(j);
                    // 设置单元格内容为字符串型
                    tempCell.setCellType(HSSFCell.CELL_TYPE_STRING);
                    tempCell.setCellValue(titles[j]);
                }
            }
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-disposition",
                    "attachment;" + "filename=" + new String(fileName.getBytes("GBK"), "ISO_8859_1") + ".xls");
            creXls.write(response.getOutputStream());
            creXls.close();
        } catch (Exception e) {
            LOGGER.error("导出excel文件失败！", e);
        }
    }

    /**
     * 功能描述: <br>
     * 〈获取Excel工作空间〉
     * 
     * @author: 14050221
     * @created: 2014年7月1日 上午11:47:30
     * @version 1.0.0
     * @param filePath
     * @return
     * @throws IOException 
     * @throws Exception
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Workbook createWb(String filePath) throws IOException  {
        if (null == filePath || "".equals(filePath)) {
            throw new IllegalArgumentException("参数不能为空");
        } else if (filePath.trim().toLowerCase().endsWith("xls")) { // Excel
                                                                    // 97~2003
                                                                    // xls
            InputStream input = new FileInputStream(filePath);
            return new HSSFWorkbook(input);
        } else if (filePath.trim().toLowerCase().endsWith("xlsx")) { // 2007 以上~
                                                                     // xlsx
            InputStream input = new FileInputStream(filePath);
            return new XSSFWorkbook(input);
        } else {
            throw new IllegalArgumentException("文件格式错误!");
        }
    }

    /**
     * 功能描述: <br>
     * 〈 获取Excel工作空间 〉
     * 
     * @author: 14050221
     * @created: 2014年7月1日 上午11:55:21
     * @version 1.0.0
     * @param file
     * @return
     * @throws IOException 
     * @throws Exception
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Workbook createWb(MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        if (fileName.trim().toLowerCase().endsWith("xls")) { // Excel 97~2003
                                                             // xls
            InputStream input = file.getInputStream();
            return new HSSFWorkbook(input);
        } else if (fileName.trim().toLowerCase().endsWith("xlsx")) { // 2007 以上~
                                                                     // xlsx
            InputStream input = file.getInputStream();
            return new XSSFWorkbook(input);
        } else {
            throw new IllegalArgumentException("文件格式错误!");
        }
    }

    /**
     * 功能描述: <br>
     * 〈根据名称获取sheet〉
     * 
     * @author: 14050221
     * @created: 2014年7月1日 上午11:56:05
     * @version 1.0.0
     * @param wb
     * @param sheetName
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static final Sheet getSheet(Workbook wb, String sheetName) {
        return wb.getSheet(sheetName);
    }

    /**
     * 功能描述: <br>
     * 〈根据索引获取sheet〉
     * 
     * @author: 14050221
     * @created: 2014年7月1日 上午11:56:19
     * @version 1.0.0
     * @param wb
     * @param index
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static final Sheet getSheet(Workbook wb, int index) {
        return wb.getSheetAt(index);
    }

    /**
     * 功能描述: <br>
     * 〈根据 sheet 页面，转化成List 列表数据〉
     * 
     * @author: 14050221
     * @created: 2014年7月1日 下午12:52:37
     * @version 1.0.0
     * @param sheet
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static final List<Object[]> listFromSheet(Sheet sheet) {
        List<Object[]> list = new ArrayList<Object[]>();
        // 制定从 第二行开始读数据 int r = sheet.getFirstRowNum()
        int maxLen = sheet.getRow(0).getLastCellNum();
        for (int r = 1; r <= sheet.getLastRowNum(); r++) {
            Row row = sheet.getRow(r);
            if (row == null)
                continue;
            // 不能用row.getPhysicalNumberOfCells()，可能会有空cell导致索引溢出
            // 使用row.getLastCellNum()至少可以保证索引不溢出，但会有很多Null值，如果使用集合的话，就不说了
            Object[] cells = new Object[maxLen];
            for (int c = row.getFirstCellNum(); c <= row.getLastCellNum(); c++) {
                Cell cell = row.getCell(c);
                if (cell == null || c >= maxLen)
                    continue;
                cells[c] = getValueFromCell(cell);
            }
            list.add(cells);
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    public static final Map<String, Object>[] mapFromSheet(Sheet sheet, String[] key) {
        // 制定从 第二行开始读数据 int r = sheet.getFirstRowNum()
        int lcn = sheet.getRow(0).getLastCellNum();
        Map<String, Object>[] m = new Map[lcn];
        for (int i = 1; i <= lcn; i++) {
            Row row = sheet.getRow(i);
            if (row == null) {
                continue;
            }
            // 不能用row.getPhysicalNumberOfCells()，可能会有空cell导致索引溢出
            // 使用row.getLastCellNum()至少可以保证索引不溢出，但会有很多Null值，如果使用集合的话，就不说了
            short rfcn = row.getFirstCellNum();
            short rlcn = row.getLastCellNum();
            m[i - 1] = new HashMap<String, Object>();
            for (int j = rfcn; j <= rlcn; j++) {
                Cell cell = row.getCell(j);
                if (cell == null || j >= lcn) {
                    continue;
                }
                m[i - 1].put(key[j], getValueFromCell(cell));
            }
        }
        return m;
    }

    /**
     * 功能描述: <br>
     * 〈获取单元格内文本信息〉
     * 
     * @author: 14050221
     * @created: 2014年7月1日 下午12:53:23
     * @version 1.0.0
     * @param cell
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static final String getValueFromCell(Cell cell) {
        if (cell == null) {
            LOGGER.warn("Cell is null !!!");
            return null;
        }
        String value = null;
        switch (cell.getCellType()) {
            case Cell.CELL_TYPE_NUMERIC: // 数字
                if (HSSFDateUtil.isCellDateFormatted(cell)) { // 如果是日期类型
                    value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cell.getDateCellValue());
                } else {
                    if (String.valueOf(cell.getNumericCellValue()).indexOf("E") > 0) {
                        value = String.valueOf((new BigDecimal(cell.getNumericCellValue())).toPlainString());
                    } else if (String.valueOf(cell.getNumericCellValue()).indexOf(".") > 0) {
                        value = String.valueOf((new Double(cell.getNumericCellValue())).intValue());
                    } else {
                        value = String.valueOf(cell.getNumericCellValue());
                    }
                }
                break;
            case Cell.CELL_TYPE_STRING: // 字符串
                value = cell.getStringCellValue();
                break;
            case Cell.CELL_TYPE_FORMULA: // 公式
                // 用数字方式获取公式结果，根据值判断是否为日期类型
                double numericValue = cell.getNumericCellValue();
                if (HSSFDateUtil.isValidExcelDate(numericValue)) { // 如果是日期类型
                    value = new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
                } else {
                    value = String.valueOf(numericValue);
                }
                break;
            case Cell.CELL_TYPE_BLANK: // 空白
                value = "";
                break;
            case Cell.CELL_TYPE_BOOLEAN: // Boolean
                value = String.valueOf(cell.getBooleanCellValue());
                break;
            case Cell.CELL_TYPE_ERROR: // Error，返回错误码
                value = String.valueOf(cell.getErrorCellValue());
                break;
            default:
                value = "";
                break;
        }

        return value;
    }

    /**
     * 功能描述: <br>
     * 根据MultipartFile file信息，读取上传的Excel文件和sheet 页面，生成Object 列表信息
     * 
     * @author: 14050221
     * @created: 2014年9月12日 下午5:09:15
     * @version 1.0.0
     * @param file
     * @return
     * @throws Exception
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static List<Object[]> getListFromExcel(MultipartFile file) throws Exception {
        List<Object[]> list = null;
        // 获取 Excel 工具空间
        Workbook workbook = createWb(file);
        // 获取Excel 的Sheet 页面
        Sheet sheet = getSheet(workbook, 0);
        // 获取 sheet 页面上面的内容，转化为 List 列表
        list = listFromSheet(sheet);
        return list;
    }

    public static Map<String, Object>[] getMapFromExcel(MultipartFile file, String[] key) throws Exception {
        // 获取 Excel 工具空间
        Workbook workbook = createWb(file);
        // 获取Excel 的Sheet 页面
        Sheet sheet = getSheet(workbook, 0);
        // 获取 sheet 页面上面的内容，转化为 List 列表
        Map<String, Object>[] m = mapFromSheet(sheet, key);
        return m;
    }

    /**
     * 功能描述: <br>
     * 根据InputStream流，读取上传的Excel文件和sheet 页面，生成Object 列表信息，只支持 07及以上版本
     * 
     * @author: 14050221
     * @created: 2014年9月12日 下午5:09:15
     * @version 1.0.0
     * @param file
     * @return
     * @throws Exception
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static List<Object[]> getListFromExcel(InputStream inputStream) throws Exception {
        List<Object[]> list = null;
        // 获取 Excel 工具空间
        Workbook workbook = new XSSFWorkbook(inputStream);
        // 获取Excel 的Sheet 页面
        Sheet sheet = getSheet(workbook, 0);
        // 获取 sheet 页面上面的内容，转化为 List 列表
        list = listFromSheet(sheet);
        return list;
    }

    public static Workbook createExcel(List<String[]> datas, String[] titles) {
        XSSFWorkbook workbook = new XSSFWorkbook();
        // 在Excel工作簿中建一工作表
        XSSFSheet sheet = workbook.createSheet();
        // 设置表头字体
        XSSFFont fontH = workbook.createFont();
        fontH.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        // 设置表头格式
        XSSFCellStyle cellStyleH = workbook.createCellStyle();
        cellStyleH.setFont(fontH);
        cellStyleH.setAlignment(XSSFCellStyle.ALIGN_CENTER);
        cellStyleH.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
        cellStyleH.setWrapText(true);

        // 设置数据字体
        XSSFFont fontI = workbook.createFont();
        fontI.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL);
        // 设置数据行格式
        XSSFCellStyle cellStyleI = workbook.createCellStyle();
        /******** 设置单元格格式为文本 add by 12061818 *****/
        XSSFDataFormat format = workbook.createDataFormat();
        cellStyleI.setDataFormat(format.getFormat("@"));
        /************************* end *******************/
        cellStyleI.setFont(fontI);
        cellStyleI.setAlignment(XSSFCellStyle.ALIGN_LEFT);
        cellStyleI.setVerticalAlignment(XSSFCellStyle.VERTICAL_BOTTOM);
        cellStyleI.setWrapText(true);

        // 创建表头
        XSSFRow rowH = sheet.createRow((short) 0);
        for (int i = 0, len = titles.length; i < len; i++) {
            XSSFCell cell = rowH.createCell(i);
            cell.setCellStyle(cellStyleI);
            cell.setCellStyle(cellStyleH);
            cell.setCellValue(titles[i]);
        }

        // 创建表内容
        for (int i = 0, size = datas.size(); i < size; i++) {
            String[] values = datas.get(i);
            XSSFRow hssfRow = sheet.createRow((short) i + 1);
            for (int j = 0, len = values.length; j < len; j++) {
                XSSFCell cellh = hssfRow.createCell(j);
                cellh.setCellStyle(cellStyleI);
                cellh.setCellStyle(cellStyleH);
                cellh.setCellValue(values[j]);
            }
        }

        return workbook;
    }

    /**
     * 
     * @param workbook
     * @param sheetName
     * @param datas
     * @param titles
     * @return
     */
    public static XSSFWorkbook createSheet(XSSFWorkbook workbook, String sheetName, List<String[]> datas,
            String[] titles) {

        // 文件副本
        if (null == workbook) {
            workbook = new XSSFWorkbook();
        }
        XSSFSheet sheet = null;

        // 在Excel工作簿中建一工作表
        if (StringUtils.isNotBlank(sheetName)) {
            sheet = workbook.createSheet(sheetName);
        } else {
            sheet = workbook.createSheet();
        }

        // 设置表头字体
        XSSFFont fontH = workbook.createFont();
        fontH.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        // 设置表头格式
        XSSFCellStyle cellStyleH = workbook.createCellStyle();
        cellStyleH.setFont(fontH);
        cellStyleH.setAlignment(XSSFCellStyle.ALIGN_CENTER);
        cellStyleH.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
        cellStyleH.setWrapText(true);

        // 设置数据字体
        XSSFFont fontI = workbook.createFont();
        fontI.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL);
        // 设置数据行格式
        XSSFCellStyle cellStyleI = workbook.createCellStyle();
        /******** 设置单元格格式为文本 add by 12061818 *****/
        XSSFDataFormat format = workbook.createDataFormat();
        cellStyleI.setDataFormat(format.getFormat("@"));
        /************************* end *******************/
        cellStyleI.setFont(fontI);
        cellStyleI.setAlignment(XSSFCellStyle.ALIGN_LEFT);
        cellStyleI.setVerticalAlignment(XSSFCellStyle.VERTICAL_BOTTOM);
        cellStyleI.setWrapText(true);

        // 创建表头
        XSSFRow rowH = sheet.createRow((short) 0);
        for (int i = 0, len = titles.length; i < len; i++) {
            XSSFCell cell = rowH.createCell(i);
            cell.setCellStyle(cellStyleI);
            cell.setCellStyle(cellStyleH);
            cell.setCellValue(titles[i]);
        }

        // 创建表内容
        for (int i = 0, size = datas.size(); i < size; i++) {
            String[] values = datas.get(i);
            XSSFRow hssfRow = sheet.createRow((short) i + 1);
            for (int j = 0, len = values.length; j < len; j++) {
                XSSFCell cellh = hssfRow.createCell(j);
                cellh.setCellStyle(cellStyleI);
                cellh.setCellStyle(cellStyleH);
                cellh.setCellValue(values[j]);
            }
        }

        return workbook;
    }

    /**
     * 
     * 功能描述:Excel 2007 通用导入导出类-导出excel <br>
     * 〈功能详细描述〉
     * 
     * @param colWidth 各列宽度，以一个汉字为一个单位
     * @param headList 标题列
     * @param objectList 内容列
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void exportExcel(OutputStream output, int[] colWidth, String[] headNames, List<Object[]> objectList)
            throws IOException {
        // 创建一个Excel文件
        SXSSFWorkbook book = new SXSSFWorkbook();
        book.setCompressTempFiles(true);// true 压缩临时文件
        // 创建一个工作簿
        Sheet sheet = book.createSheet("Sheet1");

        // 标题栏字体样式（加粗、大小、居中显示）
        CellStyle headStyle = book.createCellStyle();
        Font font = book.createFont();
        font.setBoldweight(Font.BOLDWEIGHT_BOLD);
        headStyle.setFont(font);
        headStyle.setAlignment(CellStyle.ALIGN_CENTER);
        // 居左样式
        CellStyle leftStyle = book.createCellStyle();
        leftStyle.setAlignment(CellStyle.ALIGN_LEFT);

        // 设置各列宽度
        for (int i = 0; i < colWidth.length; i++) {
            // 设置每列的宽度
            sheet.setColumnWidth(i, (short) (colWidth[i] * TWOZERO * THREESEVENFIVE));
        }

        Row rows = null;
        Cell cells = null;
        // 标题和内容
        if (headNames != null && headNames.length > 0) {
            int headSize = headNames.length;
            // 第一行 标题行
            rows = sheet.createRow(0);
            for (int i = 0; i < headSize; i++) {
                cells = rows.createCell(i);
                cells.setCellValue(headNames[i]);
                cells.setCellStyle(headStyle);
            }
            Object[] rowObj = null;
            // 里面的内容
            if (objectList != null && objectList.size() > 0) {
                for (int i = 0; i < objectList.size(); i++) {
                    rows = sheet.createRow(i + 1);
                    rowObj = objectList.get(i);
                    // 每行内容
                    for (int j = 0; j < rowObj.length; j++) {
                        // 设置每行样式 String样式
                        cells = rows.createCell(j);
                        cells.setCellStyle(leftStyle);
                        cells.setCellType(Cell.CELL_TYPE_STRING);
                        // 设置值
                        cells.setCellValue(rowObj[j] == null ? "" : rowObj[j].toString());
                    }
                }
            }
        }
        if (book != null) {
            try {
                book.write(output);
                output.flush();
                output.close();
                book.dispose();
                book.close();
            } catch (IOException e) {
                LOGGER.error("2007excel通用工具类 exportExcel异常", e);
            }
        }
    }

    /**
     * 功能描述: <br>
     * 将String 转换成utf-8用于网络传输
     *
     * @param s
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String toUtf8String(String s) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c >= ZERO && c <= TWOFIVEFIVE) {
                sb.append(c);
            } else {
                byte[] b;
                try {
                    b = Character.toString(c).getBytes("utf-8");
                } catch (UnsupportedEncodingException e) {
                    b = new byte[0];
                    LOGGER.error("toUtf8String ERROR", e);
                }
                for (int j = 0; j < b.length; j++) {
                    int k = b[j];
                    if (k < 0) {
                        k += TWOFIVESIX;
                    }
                    sb.append("%" + Integer.toHexString(k).toUpperCase());
                }
            }
        }
        return sb.toString();
    }

    /**
     * 下载excel模板文件，使用jxls2
     *
     * @param templatePath 模板文件路径
     * @param fileName 下载文件名
     * @param context 模板填充数据
     * @param response
     * @throws Exception
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void downloadTemplateExcel(String templatePath, String fileName, Context context,
            HttpServletResponse response) throws Exception {
        File templateFile = new File(templatePath);
        InputStream in = null;
        try {
            in = new FileInputStream(templateFile);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-disposition",
                    "attachment;" + "filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + "\"");
            JxlsHelper.getInstance().processTemplate(in, response.getOutputStream(), context);
            response.flushBuffer();
        } catch (Exception e) {
            throw new BizzException(e);
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }

    public static void main(String[] args) {

    }

    /**
     * 导出excel 表格
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param request
     * @param resp
     * @param fileName
     * @param sheetNames
     * @param titles
     * @param contents
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void exportExcel(HttpServletRequest request, HttpServletResponse resp, String fileName,
            List<String> sheetNames, List<List<String>> titles, List<List<List<String>>> contents) {
        // 数据校验
        if (StringUtils.isBlank(fileName) || CollectionUtils.isEmpty(sheetNames) || CollectionUtils.isEmpty(titles)
                || CollectionUtils.isEmpty(contents)) {
            return;
        } else if (sheetNames.size() != titles.size() || titles.size() != contents.size()) {
            return;
        }
        OutputStream out = null;
        try {
            HSSFWorkbook wb = new HSSFWorkbook();
            request.setCharacterEncoding("UTF-8");
            resp.setCharacterEncoding("UTF-8");
            resp.setContentType("application/x-xls");
            String tempFileName = fileName;
            if (!tempFileName.toLowerCase().endsWith(".xls")) {
                tempFileName = fileName + ".xls";
            }
            tempFileName = URLEncoder.encode(tempFileName, "UTF-8");
            resp.addHeader("Content-Disposition", "attachment;filename=" + tempFileName);
            // 处理每个sheet数据
            for (int i = 0; i < sheetNames.size(); i++) {
                createSheet(wb, sheetNames.get(i), titles.get(i), contents.get(i));
            }
            out = resp.getOutputStream();
            wb.write(out);
            wb.close();
        } catch (ServiceException e) {
            LOGGER.error("exportExcel ServiceException:" , e);
        } catch (Exception e1) {
            LOGGER.error("Exception Exception:" , e1);
        } finally {
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * 创建, 处理sheet数据
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param wb
     * @param sheetName
     * @param titles
     * @param datas
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private static void createSheet(HSSFWorkbook wb, String sheetName, List<String> titles, List<List<String>> datas) {
        HSSFSheet sheet = wb.createSheet(sheetName);
        sheet.setDefaultRowHeight((short) (2 * 256));
        sheet.setColumnWidth(0, 50 * 160);
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 16);
        // 标题行
        HSSFRow row = sheet.createRow((int) 0);
        HSSFCellStyle style = wb.createCellStyle();
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 判断标题是否为空
        if (CollectionUtils.isEmpty(titles)) {
            return;
        }
        HSSFCell cell;
        for (int i = 0; i < titles.size(); i++) {
            cell = row.createCell(i);
            cell.setCellValue(titles.get(i));
            cell.setCellStyle(style);
        }
        // 判断数据是否为空
        if (CollectionUtils.isEmpty(datas)) {
            return;
        }
        List<String> data;
        HSSFRow rowData;
        for (int i = 0; i < datas.size(); i++) {
            data = datas.get(i);
            // 判断数据是否为空
            if (CollectionUtils.isEmpty(data)) {
                continue;
            }
            //
            rowData = sheet.createRow((int) i + 1);
            for (int j = 0; j < data.size(); j++) {
                rowData.createCell(j).setCellValue(data.get(j));
            }
        }
    }
    
    /**
     * 
     * 功能描述: Excel 2007 通用导入导出类-生成excel文件<br>
     * 〈功能详细描述〉
     *
     * @param fileName
     * @param colWidth
     * @param headNames
     * @param objectList
     * @return
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static File createExcelFile(String fileName, int[] colWidth, String[] headNames, List<Object[]> objectList)
            throws IOException {
        // 创建一个Excel文件
        SXSSFWorkbook book = new SXSSFWorkbook();
        book.setCompressTempFiles(true);// true 压缩临时文件
        // 创建一个工作簿
        Sheet sheet = book.createSheet("Sheet1");

        // 标题栏字体样式（加粗、大小、居中显示）
        CellStyle headStyle = book.createCellStyle();
        Font font = book.createFont();
        font.setBoldweight(Font.BOLDWEIGHT_BOLD);
        headStyle.setFont(font);
        headStyle.setAlignment(CellStyle.ALIGN_CENTER);
        // 居左样式
        CellStyle leftStyle = book.createCellStyle();
        leftStyle.setAlignment(CellStyle.ALIGN_LEFT);

        // 设置各列宽度
        for (int i = 0; i < colWidth.length; i++) {
            // 设置每列的宽度
            sheet.setColumnWidth(i, (short) (colWidth[i] * TWOZERO * THREESEVENFIVE));
        }

        Row rows = null;
        Cell cells = null;
        // 标题和内容
        if (headNames != null && headNames.length > 0) {
            int headSize = headNames.length;
            // 第一行 标题行
            rows = sheet.createRow(0);
            for (int i = 0; i < headSize; i++) {
                cells = rows.createCell(i);
                cells.setCellValue(headNames[i]);
                cells.setCellStyle(headStyle);
            }
            Object[] rowObj = null;
            // 里面的内容
            if (objectList != null && objectList.size() > 0) {
                for (int i = 0; i < objectList.size(); i++) {
                    rows = sheet.createRow(i + 1);
                    rowObj = objectList.get(i);
                    // 每行内容
                    for (int j = 0; j < rowObj.length; j++) {
                        // 设置每行样式 String样式
                        cells = rows.createCell(j);
                        cells.setCellStyle(leftStyle);
                        cells.setCellType(Cell.CELL_TYPE_STRING);
                        // 设置值
                        cells.setCellValue(rowObj[j] == null ? "" : rowObj[j].toString());
                    }
                }
            }
        }
        File file = null;
        OutputStream output = null;
        try {
            file = File.createTempFile(fileName, ExportConstants.ExportFileSuffix.EXPORT_FILE_SUFFIX_XLSX);
            output = new FileOutputStream(file);
            book.write(output);
            output.flush();
            book.dispose();
        } catch (IOException e) {
            LOGGER.error("2007excel generic tool class exportExcel generates file exceptions", e);
        } finally {
            if (null != output) {
                output.close();
            }
            if (null != book) {
                book.close();
            }
        }
        return file;
    }
    
    public static File createExcelFile(String fileName, List<String[]> datas, String[] titles) throws IOException {
        XSSFWorkbook workbook = new XSSFWorkbook();
        // 在Excel工作簿中建一工作表
        XSSFSheet sheet = workbook.createSheet();
        // 设置表头字体
        XSSFFont fontH = workbook.createFont();
        fontH.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        // 设置表头格式
        XSSFCellStyle cellStyleH = workbook.createCellStyle();
        cellStyleH.setFont(fontH);
        cellStyleH.setAlignment(XSSFCellStyle.ALIGN_CENTER);
        cellStyleH.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
        cellStyleH.setWrapText(true);

        // 设置数据字体
        XSSFFont fontI = workbook.createFont();
        fontI.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL);
        // 设置数据行格式
        XSSFCellStyle cellStyleI = workbook.createCellStyle();
        /******** 设置单元格格式为文本 add by 12061818 *****/
        XSSFDataFormat format = workbook.createDataFormat();
        cellStyleI.setDataFormat(format.getFormat("@"));
        /************************* end *******************/
        cellStyleI.setFont(fontI);
        cellStyleI.setAlignment(XSSFCellStyle.ALIGN_LEFT);
        cellStyleI.setVerticalAlignment(XSSFCellStyle.VERTICAL_BOTTOM);
        cellStyleI.setWrapText(true);

        // 创建表头
        XSSFRow rowH = sheet.createRow((short) 0);
        for (int i = 0, len = titles.length; i < len; i++) {
            XSSFCell cell = rowH.createCell(i);
            cell.setCellStyle(cellStyleI);
            cell.setCellStyle(cellStyleH);
            cell.setCellValue(titles[i]);
        }

        // 创建表内容
        for (int i = 0, size = datas.size(); i < size; i++) {
            String[] values = datas.get(i);
            XSSFRow hssfRow = sheet.createRow((short) i + 1);
            for (int j = 0, len = values.length; j < len; j++) {
                XSSFCell cellh = hssfRow.createCell(j);
                cellh.setCellStyle(cellStyleI);
                cellh.setCellStyle(cellStyleH);
                cellh.setCellValue(values[j]);
            }
        }

        File file = null;
        OutputStream output = null;
        try {
            file = File.createTempFile(fileName, ExportConstants.ExportFileSuffix.EXPORT_FILE_SUFFIX_XLSX);
            output = new FileOutputStream(file);
            workbook.write(output);
            output.flush();
        } catch (IOException e) {
            LOGGER.error("2007excel generic tool class exportExcel generates file exceptions", e);
        } finally {
            if (null != output) {
                output.close();
            }
            if (null != workbook) {
                workbook.close();
            }
        }
    
        return file;
    }

}
